home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 25 / AACD 25.iso / AACD / Utilities / BasiliskII / src / adb.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-02-02  |  10.1 KB  |  402 lines

  1. /*
  2.  *  adb.cpp - ADB emulation (mouse/keyboard)
  3.  *
  4.  *  Basilisk II (C) 1997-2001 Christian Bauer
  5.  *
  6.  *  This program is free software; you can redistribute it and/or modify
  7.  *  it under the terms of the GNU General Public License as published by
  8.  *  the Free Software Foundation; either version 2 of the License, or
  9.  *  (at your option) any later version.
  10.  *
  11.  *  This program is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *  GNU General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU General Public License
  17.  *  along with this program; if not, write to the Free Software
  18.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19.  */
  20.  
  21. /*
  22.  *  SEE ALSO
  23.  *    Inside Macintosh: Devices, chapter 5 "ADB Manager"
  24.  *    Technote HW 01: "ADB - The Untold Story: Space Aliens Ate My Mouse"
  25.  */
  26.  
  27. #include <stdlib.h>
  28.  
  29. #include "sysdeps.h"
  30. #include "cpu_emulation.h"
  31. #include "main.h"
  32. #include "emul_op.h"
  33. #include "video.h"
  34. #include "adb.h"
  35.  
  36. #define DEBUG 0
  37. #include "debug.h"
  38.  
  39.  
  40. // Global variables
  41. static int mouse_x = 0, mouse_y = 0;                            // Mouse position
  42. static int old_mouse_x = 0, old_mouse_y = 0;
  43. static bool mouse_button[3] = {false, false, false};            // Mouse button states
  44. static bool old_mouse_button[3] = {false, false, false};
  45. static bool relative_mouse = false;
  46.  
  47. static uint8 key_states[16];                // Key states (Mac keycodes)
  48. #define MATRIX(code) (key_states[code >> 3] & (1 << (~code & 7)))
  49.  
  50. // Keyboard event buffer (Mac keycodes with up/down flag)
  51. const int KEY_BUFFER_SIZE = 16;
  52. static uint8 key_buffer[KEY_BUFFER_SIZE];
  53. static unsigned int key_read_ptr = 0, key_write_ptr = 0;
  54.  
  55. static uint8 mouse_reg_3[2] = {0x63, 0x01};    // Mouse ADB register 3
  56.  
  57. static uint8 key_reg_2[2] = {0xff, 0xff};    // Keyboard ADB register 2
  58. static uint8 key_reg_3[2] = {0x62, 0x05};    // Keyboard ADB register 3
  59.  
  60.  
  61. /*
  62.  *  ADBOp() replacement
  63.  */
  64.  
  65. void ADBOp(uint8 op, uint8 *data)
  66. {
  67.     D(bug("ADBOp op %02x, data %02x %02x %02x\n", op, data[0], data[1], data[2]));
  68.  
  69.     // ADB reset?
  70.     if ((op & 0x0f) == 0) {
  71.         mouse_reg_3[0] = 0x63;
  72.         mouse_reg_3[1] = 0x01;
  73.         key_reg_2[0] = 0xff;
  74.         key_reg_2[1] = 0xff;
  75.         key_reg_3[0] = 0x62;
  76.         key_reg_3[1] = 0x05;
  77.         return;
  78.     }
  79.  
  80.     // Cut op into fields
  81.     uint8 adr = op >> 4;
  82.     uint8 cmd = (op >> 2) & 3;
  83.     uint8 reg = op & 3;
  84.  
  85.     // Check which device was addressed and act accordingly
  86.     if (adr == (mouse_reg_3[0] & 0x0f)) {
  87.  
  88.         // Mouse
  89.         if (cmd == 2) {
  90.  
  91.             // Listen
  92.             switch (reg) {
  93.                 case 3:        // Address/HandlerID
  94.                     if (data[2] == 0xfe)            // Change address
  95.                         mouse_reg_3[0] = (mouse_reg_3[0] & 0xf0) | (data[1] & 0x0f);
  96.                     else if (data[2] == 1 || data[2] == 2 || data[2] == 4)    // Change device handler ID
  97.                         mouse_reg_3[1] = data[2];
  98.                     else if (data[2] == 0x00)        // Change address and enable bit
  99.                         mouse_reg_3[0] = (mouse_reg_3[0] & 0xd0) | (data[1] & 0x2f);
  100.                     break;
  101.             }
  102.  
  103.         } else if (cmd == 3) {
  104.  
  105.             // Talk
  106.             switch (reg) {
  107.                 case 1:        // Extended mouse protocol
  108.                     data[0] = 8;
  109.                     data[1] = 'a';                // Identifier
  110.                     data[2] = 'p';
  111.                     data[3] = 'p';
  112.                     data[4] = 'l';
  113.                     data[5] = 300 >> 8;            // Resolution (dpi)
  114.                     data[6] = 300 & 0xff;
  115.                     data[7] = 1;                // Class (mouse)
  116.                     data[8] = 3;                // Number of buttons
  117.                     break;
  118.                 case 3:        // Address/HandlerID
  119.                     data[0] = 2;
  120.                     data[1] = mouse_reg_3[0] & 0xf0 | (rand() & 0x0f);
  121.                     data[2] = mouse_reg_3[1];
  122.                     break;
  123.                 default:
  124.                     data[0] = 0;
  125.                     break;
  126.             }
  127.         }
  128.         D(bug(" mouse reg 3 %02x%02x\n", mouse_reg_3[0], mouse_reg_3[1]));
  129.  
  130.     } else if (adr == (key_reg_3[0] & 0x0f)) {
  131.  
  132.         // Keyboard
  133.         if (cmd == 2) {
  134.  
  135.             // Listen
  136.             switch (reg) {
  137.                 case 2:        // LEDs/Modifiers
  138.                     key_reg_2[0] = data[1];
  139.                     key_reg_2[1] = data[2];
  140.                     break;
  141.                 case 3:        // Address/HandlerID
  142.                     if (data[2] == 0xfe)            // Change address
  143.                             key_reg_3[0] = (key_reg_3[0] & 0xf0) | (data[1] & 0x0f);
  144.                     else if (data[2] == 0x00)        // Change address and enable bit
  145.                         key_reg_3[0] = (key_reg_3[0] & 0xd0) | (data[1] & 0x2f);
  146.                     break;
  147.             }
  148.  
  149.         } else if (cmd == 3) {
  150.  
  151.             // Talk
  152.             switch (reg) {
  153.                 case 2: {    // LEDs/Modifiers
  154.                     uint8 reg2hi = 0xff;
  155.                     uint8 reg2lo = key_reg_2[1] | 0xf8;
  156.                     if (MATRIX(0x6b))    // Scroll Lock
  157.                         reg2lo &= ~0x40;
  158.                     if (MATRIX(0x47))    // Num Lock
  159.                         reg2lo &= ~0x80;
  160.                     if (MATRIX(0x37))    // Command
  161.                         reg2hi &= ~0x01;
  162.                     if (MATRIX(0x3a))    // Option
  163.                         reg2hi &= ~0x02;
  164.                     if (MATRIX(0x38))    // Shift
  165.                         reg2hi &= ~0x04;
  166.                     if (MATRIX(0x36))    // Control
  167.                         reg2hi &= ~0x08;
  168.                     if (MATRIX(0x39))    // Caps Lock
  169.                         reg2hi &= ~0x20;
  170.                     if (MATRIX(0x75))    // Delete
  171.                         reg2hi &= ~0x40;
  172.                     data[0] = 2;
  173.                     data[1] = reg2hi;
  174.                     data[2] = reg2lo;
  175.                     break;
  176.                 }
  177.                 case 3:        // Address/HandlerID
  178.                     data[0] = 2;
  179.                     data[1] = key_reg_3[0] & 0xf0 | (rand() & 0x0f);
  180.                     data[2] = key_reg_3[1];
  181.                     break;
  182.                 default:
  183.                     data[0] = 0;
  184.                     break;
  185.             }
  186.         }
  187.         D(bug(" keyboard reg 3 %02x%02x\n", key_reg_3[0], key_reg_3[1]));
  188.  
  189.     } else                                                // Unknown address
  190.         if (cmd == 3)
  191.             data[0] = 0;                                // Talk: 0 bytes of data
  192. }
  193.  
  194.  
  195. /*
  196.  *  Mouse was moved (x/y are absolute or relative, depending on ADBSetRelMouseMode())
  197.  */
  198.  
  199. void ADBMouseMoved(int x, int y)
  200. {
  201.     if (relative_mouse) {
  202.         mouse_x += x; mouse_y += y;
  203.     } else {
  204.         mouse_x = x; mouse_y = y;
  205.     }
  206. }
  207.  
  208.  
  209. /* 
  210.  *  Mouse button pressed
  211.  */
  212.  
  213. void ADBMouseDown(int button)
  214. {
  215.     mouse_button[button] = true;
  216. }
  217.  
  218.  
  219. /*
  220.  *  First mouse button released
  221.  */
  222.  
  223. void ADBMouseUp(int button)
  224. {
  225.     mouse_button[button] = false;
  226. }
  227.  
  228.  
  229. /*
  230.  *  Set mouse mode (absolute or relative)
  231.  */
  232.  
  233. void ADBSetRelMouseMode(bool relative)
  234. {
  235.     relative_mouse = relative;
  236. }
  237.  
  238.  
  239. /*
  240.  *  Key pressed ("code" is the Mac key code)
  241.  */
  242.  
  243. void ADBKeyDown(int code)
  244. {
  245.     // Add keycode to buffer
  246.     key_buffer[key_write_ptr] = code;
  247.     key_write_ptr = (key_write_ptr + 1) % KEY_BUFFER_SIZE;
  248.  
  249.     // Set key in matrix
  250.     key_states[code >> 3] |= (1 << (~code & 7));
  251. }
  252.  
  253.  
  254. /*
  255.  *  Key released ("code" is the Mac key code)
  256.  */
  257.  
  258. void ADBKeyUp(int code)
  259. {
  260.     // Add keycode to buffer
  261.     key_buffer[key_write_ptr] = code | 0x80;    // Key-up flag
  262.     key_write_ptr = (key_write_ptr + 1) % KEY_BUFFER_SIZE;
  263.  
  264.     // Clear key in matrix
  265.     key_states[code >> 3] &= ~(1 << (~code & 7));
  266. }
  267.  
  268.  
  269. /*
  270.  *  ADB interrupt function (executed as part of 60Hz interrupt)
  271.  */
  272.  
  273. void ADBInterrupt(void)
  274. {
  275.     M68kRegisters r;
  276.  
  277.     // Return if ADB is not initialized
  278.     uint32 adb_base = ReadMacInt32(0xcf8);
  279.     if (!adb_base || adb_base == 0xffffffff)
  280.         return;
  281.     uint32 tmp_data = adb_base + 0x163;    // Temporary storage for faked ADB data
  282.  
  283.     // Get position so that it won't change during processing
  284.     int mx = mouse_x;
  285.     int my = mouse_y;
  286.  
  287.     uint32 key_base = adb_base + 4;
  288.     uint32 mouse_base = adb_base + 16;
  289.  
  290.     if (relative_mouse) {
  291.  
  292.         // Mouse movement (relative) and buttons
  293.         if (mx != 0 || my != 0 || mouse_button[0] != old_mouse_button[0] || mouse_button[1] != old_mouse_button[1] || mouse_button[2] != old_mouse_button[2]) {
  294.  
  295.             // Call mouse ADB handler
  296.             if (mouse_reg_3[1] == 4) {
  297.                 // Extended mouse protocol
  298.                 WriteMacInt8(tmp_data, 3);
  299.                 WriteMacInt8(tmp_data + 1, (my & 0x7f) | (mouse_button[0] ? 0 : 0x80));
  300.                 WriteMacInt8(tmp_data + 2, (mx & 0x7f) | (mouse_button[1] ? 0 : 0x80));
  301.                 WriteMacInt8(tmp_data + 3, ((my >> 3) & 0x70) | ((mx >> 7) & 0x07) | (mouse_button[2] ? 0x08 : 0x88));
  302.             } else {
  303.                 // 100/200 dpi mode
  304.                 WriteMacInt8(tmp_data, 2);
  305.                 WriteMacInt8(tmp_data + 1, (my & 0x7f) | (mouse_button[0] ? 0 : 0x80));
  306.                 WriteMacInt8(tmp_data + 2, (mx & 0x7f) | (mouse_button[1] ? 0 : 0x80));
  307.             }    
  308.             r.a[0] = tmp_data;
  309.             r.a[1] = ReadMacInt32(mouse_base);
  310.             r.a[2] = ReadMacInt32(mouse_base + 4);
  311.             r.a[3] = adb_base;
  312.             r.d[0] = (mouse_reg_3[0] << 4) | 0x0c;    // Talk 0
  313.             Execute68k(r.a[1], &r);
  314.  
  315.             mouse_x = mouse_y = 0;
  316.             old_mouse_button[0] = mouse_button[0];
  317.             old_mouse_button[1] = mouse_button[1];
  318.             old_mouse_button[2] = mouse_button[2];
  319.         }
  320.  
  321.     } else {
  322.  
  323.         // Update mouse position (absolute)
  324.         if (mx != old_mouse_x || my != old_mouse_y) {
  325. #ifdef POWERPC_ROM
  326.             static const uint16 proc[] = {
  327.                 0x2f08,        // move.l a0,-(sp)
  328.                 0x2f00,        // move.l d0,-(sp)
  329.                 0x2f01,        // move.l d1,-(sp)
  330.                 0x7001,        // moveq #1,d0 (MoveTo)
  331.                 0xaadb,        // CursorDeviceDispatch
  332.                 M68K_RTS
  333.             };
  334.             r.a[0] = ReadMacInt32(mouse_base + 4);
  335.             r.d[0] = mx;
  336.             r.d[1] = my;
  337.             Execute68k((uint32)proc, &r);
  338. #else
  339.             WriteMacInt16(0x82a, mx);
  340.             WriteMacInt16(0x828, my);
  341.             WriteMacInt16(0x82e, mx);
  342.             WriteMacInt16(0x82c, my);
  343.             WriteMacInt8(0x8ce, ReadMacInt8(0x8cf));    // CrsrCouple -> CrsrNew
  344. #endif
  345.             old_mouse_x = mx;
  346.             old_mouse_y = my;
  347.         }
  348.  
  349.         // Send mouse button events
  350.         if (mouse_button[0] != old_mouse_button[0]) {
  351.             uint32 mouse_base = adb_base + 16;
  352.  
  353.             // Call mouse ADB handler
  354.             if (mouse_reg_3[1] == 4) {
  355.                 // Extended mouse protocol
  356.                 WriteMacInt8(tmp_data, 3);
  357.                 WriteMacInt8(tmp_data + 1, mouse_button[0] ? 0 : 0x80);
  358.                 WriteMacInt8(tmp_data + 2, mouse_button[1] ? 0 : 0x80);
  359.                 WriteMacInt8(tmp_data + 3, mouse_button[2] ? 0x08 : 0x88);
  360.             } else {
  361.                 // 100/200 dpi mode
  362.                 WriteMacInt8(tmp_data, 2);
  363.                 WriteMacInt8(tmp_data + 1, mouse_button[0] ? 0 : 0x80);
  364.                 WriteMacInt8(tmp_data + 2, mouse_button[1] ? 0 : 0x80);
  365.             }
  366.             r.a[0] = tmp_data;
  367.             r.a[1] = ReadMacInt32(mouse_base);
  368.             r.a[2] = ReadMacInt32(mouse_base + 4);
  369.             r.a[3] = adb_base;
  370.             r.d[0] = (mouse_reg_3[0] << 4) | 0x0c;    // Talk 0
  371.             Execute68k(r.a[1], &r);
  372.  
  373.             old_mouse_button[0] = mouse_button[0];
  374.             old_mouse_button[1] = mouse_button[1];
  375.             old_mouse_button[2] = mouse_button[2];
  376.         }
  377.     }
  378.  
  379.     // Process accumulated keyboard events
  380.     while (key_read_ptr != key_write_ptr) {
  381.  
  382.         // Read keyboard event
  383.         uint8 mac_code = key_buffer[key_read_ptr];
  384.         key_read_ptr = (key_read_ptr + 1) % KEY_BUFFER_SIZE;
  385.  
  386.         // Call keyboard ADB handler
  387.         WriteMacInt8(tmp_data, 2);
  388.         WriteMacInt8(tmp_data + 1, mac_code);
  389.         WriteMacInt8(tmp_data + 2, mac_code == 0x7f ? 0x7f : 0xff);    // Power key is special
  390.         r.a[0] = tmp_data;
  391.         r.a[1] = ReadMacInt32(key_base);
  392.         r.a[2] = ReadMacInt32(key_base + 4);
  393.         r.a[3] = adb_base;
  394.         r.d[0] = (key_reg_3[0] << 4) | 0x0c;    // Talk 0
  395.         Execute68k(r.a[1], &r);
  396.     }
  397.  
  398.     // Clear temporary data
  399.     WriteMacInt32(tmp_data, 0);
  400.     WriteMacInt32(tmp_data + 4, 0);
  401. }
  402.